3D Graphics Programming with QuickDraw 3D 1.5.4
Previous | QD3D Book | Overview | Chapter Contents | Next |
Custom objects should provide methods for registering, unregistering, and replacing classes.
Listing 7 provides an example of how these methods are called. It is based on the example discussed in "Creating a Hierarchy" .
Listing 7 Sample of registering and unregistering classes
#define kMethodTypeFooGroupDoSomething \
Q3_METHOD_TYPE(0xFE, `f','g','r')
typedef TQ3Status (*TFooGroupDoSomethingMethod)(
TQ3ObjectClass objectClass,
TQ3Object object,
float *dummyArg);
typedef struct TFooGroupClass {
TFooGroupDoSomethingMethod doSomething;
} TFooGroupClass;
typedef struct TFooGroupData {
float dummy1;
} TFooGroupData;
gFooGroupClass =
Q3XObjectHierarchy_RegisterClass(
kQ3ShapeTypeGroup,
kGroupTypeFoo,
"SomeCompany:FooGroup",
FooGroupClass_MetaHandler,
FooGroupClass_VirtualMetaHandler,
sizeof(TFooGroupClass),
sizeof(TFooGroupData));
The registration method for the foregoing would look like this:
static TQ3Status FooGroupClass_Register(
TQ3ObjectClass objectClass,
TFooGroupClass *gClass)
{
gClass->doSomething =
Q3XObjectHierarchy_GetMethod(
objectClass,
kMethodTypeFooGroupDoSomething);
if ((Q3XObjectClass_GetLeafType(objectClass) !=
kGroupTypeFoo) &&
(gClass->doSomething == NULL)) {
return kQ3Failure;
}
return kQ3Success;
}
When the parent class FooGroup is registered in this example, there is no need for the kMethodTypeGroupFoo method. In subclasses, however, this method is required. This type of strategy may be used to impose restrictions on subclasses only, especially when the parent class is never intended to be instantiated.
There is also no need for an ObjectClassUnregister method because the ObjectClassRegister method does not allocate any data.
The TQ3XObjectClassRegisterMethod function, which is returned by the kQ3XMethodTypeObjectClassRegister method, registers a class.
#define kQ3XMethodTypeObjectClassRegister Q3_METHOD_TYPE('r','g','s','t')
typedef TQ3Status (*TQ3XObjectClassRegisterMethod)(
TQ3XObjectClass objectClass,
void *classPrivate);
The TQ3XObjectClassRegisterMethod method registers the class designated by objectClass, with private data pointed to by classPrivate. The size of the private data is equivalent to the methodsSize parameter used in the earlier Q3XObjectHierarchy_RegisterClass call; if methodsSize was 0, classPrivate is NULL .
ObjectClassRegister is called from Q3ObjectHierarchy_RegisterClass upon initial registration of an object class. It is also called when any subclass of an object class is registered. Registration occurs from root to leaf, as shown in Figure 8 . The ObjectClassRegister method is called for the private class data on the way down the hierarchy, and the ObjectClassUnregister method is called on the way up in case of a failure.
ObjectClassRegister should initialize the data in classPrivate and collect any needed methods from the metahandler, using Q3ObjectHierarchy_GetMethod . A class may have no private class data (that is, its methodsSize may be 0), yet may still have an ObjectClassRegister method. In this case, classPrivate will be NULL (since there is no data), and a particular class could instead keep track of subclass states in global variables.
The TQ3XObjectClassUnregisterMethod function, which is returned by the kQ3XMethodTypeObjectClassUnregister method, unregisters a class.
#define kQ3XMethodTypeObjectClassUnregister Q3_METHOD_TYPE('u','n','r','g')
typedef void (*TQ3XObjectClassUnregisterMethod)(
TQ3XObjectClass objectClass,
void *classPrivate);
The TQ3XObjectClassUnregisterMethod method unregisters the class designated by objectClass, which has private data pointed to by classPrivate. The size of the private data is equivalent to the methodsSize parameter used in the earlier Q3XObjectHierarchy_RegisterClass call; if methodsSize was 0, classPrivate is NULL .
The ObjectClassUnregister method should undo any operations performed in the ObjectClassRegister method, including removing the class from global tables and deallocating any memory used to store the class private data. If the ObjectClassRegister method performed no allocations, ObjectClassUnregister may be NULL .
The TQ3XObjectClassReplaceMethod function, which is returned by the kQ3XMethodTypeObjectClassReplace method, replaces one class with another. It is used only when a new version of an object class is registered, eliminating the old version.
#define kQ3XMethodTypeObjectClassReplace Q3_METHOD_TYPE('r','g','r','p')
typedef void (*TQ3XObjectClassReplaceMethod)(
TQ3XObjectClass oldObjectClass,
void *oldClassPrivate,
TQ3XObjectClass newObjectClass,
void *newClassPrivate);
The TQ3XObjectClassReplaceMethod method replaces the class designated by oldObjectClass, which has private data pointed to by oldClassPrivate, with the class designated by newObjectClass, which has private data pointed to by newClassPrivate. The sizes of the private data areas are equivalent to the methodsSize parameters used in the earlier Q3XObjectHierarchy_RegisterClass calls; if a methodsSize value was 0, its equivalent classPrivate value is NULL .
TQ3XObjectClassReplaceMethod is required only by classes that maintain or track their subclasses in a table. When object classes of the same type collide, use the replace method instead of calling Unregister(oldClass, oldClassPrivate) followed by Register(newClass, newClassPrivate) , which may cause an unexpected failure.
The replace method should register the new class and then unregister the old class, without failure. If a class's TQ3XObjectClassRegisterMethod method never fails, the replace method is not needed.
Previous | QD3D Book | Overview | Chapter Contents | Next |